#include "crop.cpp"
#include <stdio.h>
#include <string.h>
#include "fileparser.cpp"

int main(int argc, char **argv) {
	int p = 16, rank = 0;
	MPI_Init(&argc, &argv);
	MPI_Comm_rank(MPI_COMM_WORLD, &rank);
	MPI_Comm_size(MPI_COMM_WORLD, &p);
	long total = 90002288;
	//fprintf(stderr,"Starting at \n");
	string DIR = "../../data/";
	string FILENAME = argv[1];
	FILENAME = DIR + FILENAME;
	const char * FILEPATH = FILENAME.c_str();
	int k = atoi(argv[2]);
	int * resvbuf;
	for (int i = 9; i < 10; i++) {
		p = pow(2, i);
		clock_t start = clock();
		double dist = 0.0;
		for (int j = 0; j < 3; j++) {
			Crop<StreamSummaryBucket> *crop = new Crop<StreamSummaryBucket>(
					rank, p, k);
			MMapFileParser *fp = new MMapFileParser((char*) FILEPATH); // Change to command arg
			//fprintf(stderr,"Init done\n");

			while (fp->getinput()) {
				/*		for (int i = 0; i < fp.count; i++) {
				 fprintf(stderr,"(%d,%.4f)", fp.IR_PTR[i], fp.NUM_PTR[i]);
				 }*/
				crop->crop((int*) fp->IR_PTR, fp->NUM_PTR, fp->count);
			}
			//fprintf(stderr,"dist at %d: %d\n", rank, crop->pdist[rank]);

			/*Entry *entries = (Entry*) malloc(k * sizeof(Entry));
			 crop->get_summary(entries);
			 free(entries);*/
			//printf ("summarysize: %d\n", crop->summarysize());
			dist += crop->pdist[rank];

			delete crop;
			delete fp;
			//printf ("summarysize: %d\n", crop->summarysize());
		}

		clock_t ends = clock();
		if (rank == 0) {
			resvbuf = (int*) malloc(sizeof(double) * p);
		}
		dist = dist/3.0;

		MPI_Gather(&dist, 1, MPI_DOUBLE, resvbuf, 1, MPI_DOUBLE, 0,
				MPI_COMM_WORLD);

		if (rank == 0) {
			cerr << p << "\t"
					<< (double) ((ends - start) / (CLOCKS_PER_SEC * 3.0))
					<< endl;
			double t = (double) ((ends - start) / (CLOCKS_PER_SEC * 3.0));
			double mean = (double) total / p;
			double error = 0.0;
			for (int i =0; i < p; i++) {
				error += pow(abs(resvbuf[i]-mean),2);
			}

			fprintf(stdout, "%d\t%.4f\t%.6f\n", p, t, sqrt(error));
		}

	}
	fprintf(stderr, "finished\n");
	free(resvbuf);
	MPI_Finalize();
	/*cerr << "Running Time : " << (double) (ends - start) / CLOCKS_PER_SEC
	 << endl;*/
	return 1;
}
